package com.juyu.miliao.api.service;


import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.api.constant.DepositType;
import com.juyu.miliao.api.dao.mysql.*;
import com.juyu.miliao.api.dao.redis.CoolSummerActivitiesRedisDao;
import com.juyu.miliao.api.dao.redis.StatisticsSummerActivityRedisDao;
import com.juyu.miliao.api.dao.redis.usercache.UserCacheVo;
import com.juyu.miliao.api.dao.redis.usercache.UserInfoCache;
import com.juyu.miliao.api.domain.*;
import com.juyu.miliao.api.domain.vo.*;
import com.juyu.miliao.api.rabbitMQ.BillDetailBeansMq;
import com.juyu.miliao.api.util.ActivityRewardLogBuilder;
import com.juyu.miliao.api.util.PageUtil;
import com.juyu.miliao.common.builder.BillDetailBeansMqMessageBuilder;
import com.juyu.miliao.common.constant.BeansType;
import com.juyu.miliao.common.domain.BillDetailBeans;
import com.juyu.miliao.common.domain.dto.BillDetailBeansDTO;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import com.juyu.miliao.common.util.DateUtil;
import com.juyu.miliao.common.util.DoubleFormatUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xuanqicheng
 */
@Service
@Slf4j
public class CoolSummerActivitiesService {
    private static final String TIME_KEY = "coolSummerActivities";
    @Autowired
    private CoolSummerActivitiesRedisDao coolSummerActivitiesRedisDao;

    @Autowired
    private CoolSummerActivitiesDao coolSummerActivitiesDao;

    @Autowired
    private AppKeyService appKeyService;

    @Autowired
    private CoolSummerRankingListDao coolSummerRankingListDao;

    @Autowired
    private UserWalletDao userWalletDao;

    @Autowired
    private BillDetailDao billDetailDao;

    @Autowired
    private ActivityRewardLogDao activityRewardLogDao;

    @Autowired
    private UserInfoCache userInfoCache;

    @Autowired
    private BillDetailBeansMq billDetailBeansMq;

    @Autowired
    private StatisticsSummerActivityRedisDao statisticsSummerActivityRedisDao;


    /**
     * 设置奖池
     *
     * @param userId
     * @param fee       充值金额，取整
     * @param localDateTime 充值时间
     */
    @Transactional(rollbackFor = Exception.class)
    public void jackpot(long userId, double fee, LocalDateTime localDateTime) {

        Appkey appkey = appKeyService.getAppKeyByKey(TIME_KEY);
        if (appkey != null) {
            JSONObject json = JSONObject.parseObject(appkey.getValue());

            String startDateTarget = json.getString("startDate");

            String endDateTarget = json.getString("endDate");

            LocalDate startDate = LocalDate.parse(startDateTarget,
                    DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            LocalDate endDate = LocalDate.parse(endDateTarget,
                    DateTimeFormatter.ofPattern("yyyy-MM-dd"));


            if (DateUtil.checkBetweenTime(startDate, endDate, localDateTime.toLocalDate())) {
                CoolSummerRankingList obj = coolSummerRankingListDao.getCoolSummerRankingListByUserId(userId);
                if (obj == null) {
                    obj = new CoolSummerRankingList();
                    obj.setRechargeAmount(new BigDecimal(fee + ""));
                    obj.setUserId(userId);
                    coolSummerRankingListDao.insertCoolSummerRankingList(obj);
                } else {
                    CoolSummerRankingList entity = new CoolSummerRankingList();
                    entity.setUserId(userId);
                    entity.setRechargeAmount(new BigDecimal(fee + ""));
                    coolSummerRankingListDao.updateCoolSummerRankingList(entity);
                }

                coolSummerActivitiesRedisDao.updateJackpot((int) fee);

                coolSummerActivitiesRedisDao.updateUserRechargeAmount(userId, fee, localDateTime);

                coolSummerActivitiesRedisDao.updateUserRechargeAmountDetail(userId,fee,localDateTime);

                coolSummerActivitiesRedisDao.updateUserCountRechargeAmount(userId,fee,localDateTime);
            }

        }

    }

    public CoolSummerJackpotVO getJackpot() {
        CoolSummerJackpotVO coolSummerJackpotVO = coolSummerActivitiesRedisDao.getJackpot();
        return coolSummerJackpotVO;
    }

    /**
     * 获取领奖列表
     *
     * @param userId
     * @return
     */
    public CoolSummerActivitiesResultVO getCoolSummerActivitiesList(long userId) {
        CoolSummerActivitiesResultVO vo = new CoolSummerActivitiesResultVO();
        LocalDate day = LocalDate.now();
        List<CoolSummerActivitiesVO> resultList = new ArrayList<>();

        List<CoolSummerActivities> list = coolSummerActivitiesDao.getCoolSummerActivitiesList();

        for (CoolSummerActivities obj : list) {

            CoolSummerActivitiesVO coolSummerActivitiesVO = new CoolSummerActivitiesVO();

            BeanUtils.copyProperties(obj, coolSummerActivitiesVO);

            boolean bl = coolSummerActivitiesRedisDao.checkUserGetRewards(userId, day, obj.getId());

            double rechargeAmount = coolSummerActivitiesRedisDao.getUserRechargeAmount(userId, day);

            if (!bl) {
                if (rechargeAmount >= obj.getThreshold().doubleValue()) {
                    coolSummerActivitiesVO.setStatus(1);
                } else {
                    coolSummerActivitiesVO.setStatus(0);
                }
            } else {
                coolSummerActivitiesVO.setStatus(2);
            }
            resultList.add(coolSummerActivitiesVO);
        }
        vo.setList(resultList);
        double rechargeAmount=coolSummerActivitiesRedisDao.getUserRechargeAmount(userId,LocalDate.now());
        Map<String,Object> userMap = new HashMap<>(1);
        userMap.put("rechargeAmount",DoubleFormatUtil.doubleFormate(rechargeAmount)+"");
        vo.setUserDetail(userMap);
        return vo;
    }

    /**
     * 领取奖励
     *
     * @param userId
     */
    public void getRewards(long userId, int activitiesId) {

        Appkey appkey = appKeyService.getAppKeyByKey(TIME_KEY);

        LocalDate localDate = LocalDate.now();

        if (appkey != null) {

            JSONObject json = JSONObject.parseObject(appkey.getValue());

            String startDateTarget = json.getString("startDate");

            String endDateTarget = json.getString("endDate");

            LocalDate startDate = LocalDate.parse(startDateTarget,
                    DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            LocalDate endDate = LocalDate.parse(endDateTarget,
                    DateTimeFormatter.ofPattern("yyyy-MM-dd"));


            if (DateUtil.checkBetweenTime(startDate, endDate, localDate)) {

                CoolSummerActivities coolSummerActivities = coolSummerActivitiesDao
                        .getCoolSummerActivitiesById(activitiesId);
                if(coolSummerActivities==null){
                    throw new ConsumeRuntimeException("activitiesId不正确");
                }
                double rechargeAmount = coolSummerActivitiesRedisDao.getUserRechargeAmount(userId, localDate);

                if (rechargeAmount >= coolSummerActivities.getThreshold().doubleValue()) {

                    long num = coolSummerActivitiesRedisDao.addUserGetRewards(userId, localDate, activitiesId);
                    if (num == 1) {
                        //用户没有领取过进行领取
                        try {
                            saveRewardsInfo(userId, coolSummerActivities.getReceiveBeans(),
                                    coolSummerActivities.getReceiveCoin(),localDate,activitiesId);
                        } catch (Exception ex) {
                            coolSummerActivitiesRedisDao.removeUserGetRewards(userId, localDate, activitiesId);
                            log.error("领取奖励错误回滚redis:userId=[{}],activitiesId=[{}],day=[{}]",
                                    userId, activitiesId, localDate);
                            log.error("领取奖励错误:ex={}", ex.getMessage());
                        }
                    }else {
                        throw new ConsumeRuntimeException("请勿重复领取");
                    }
                }else{
                    throw new ConsumeRuntimeException("没有达到领取资格");
                }
            }else{
                throw new ConsumeRuntimeException("活动已过期");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveRewardsInfo(long userId, long receiveBeans, long receiveCoin,LocalDate localDate,
                                int activitiesId) {
        UserWallet entity = new UserWallet();
        entity.setDeposit((int) receiveCoin);
        entity.setBeans(receiveBeans);
        entity.setUserId(userId);

        long fag = userWalletDao.plusUserWalletBeansAndDeposit(entity);

        if (fag == 1) {

            BillDetailDeposit billDetailDeposit = new BillDetailDeposit();
            BillDetailBeans billDetailBeans = new BillDetailBeans();
            //记寻币账单
            billDetailDeposit.setRecordType(DepositType.COOL_SUMMER_GET_COIN.getCode());
            billDetailDeposit.setInUserId(0);
            billDetailDeposit.setOutUserId(userId);
            billDetailDeposit.setSpend((int) receiveCoin);
            billDetailDeposit.setDiamond(0);
            billDetailDeposit.setRatio(0);
            billDetailDao.insertBillDetailDeposit(billDetailDeposit);
            //记寻豆账单
            billDetailBeans.setBeansType(BeansType.COOL_SUMMER_GET_BEANS.getCode());
            billDetailBeans.setBeans(receiveBeans);
            billDetailBeans.setRatio(0);
            billDetailBeans.setUserId(userId);
            billDetailDao.insertBillDetailBeans(billDetailBeans);

            //记录领取奖励明细
            ActivityRewardLogBuilder builder = new ActivityRewardLogBuilder();
            ActivityRewardLog activityRewardLog = builder.userId(userId).deposit(receiveCoin)
                    .beans(receiveBeans).type(1).build();

            activityRewardLogDao.insertActivityRewardLog(activityRewardLog);
            /**
             * 统计用户领取奖励
             */
            coolSummerActivitiesRedisDao.statisticsUserGetRewards(userId,localDate,activitiesId);
            /**
             * 统计用户领取奖励人数
             */
            statisticsSummerActivityRedisDao.summerActivityGetRewardsNumbers(userId);

            /**
             * 统计活动寻币支出
             */
            statisticsSummerActivityRedisDao.summerActivityExpenditureCoin(receiveCoin);

            /**
             * 统计活动寻豆支出
             */
            statisticsSummerActivityRedisDao.summerActivityExpenditureBeans(receiveBeans);

        }

    }

    /**
     * 获取领取奖励日志
     * @param userId
     * @param type
     * @return
     */
    public List<ActivityRewardLogVO> getRewardsLog(long userId, int type,int page,int pageSize) {
        int startNum = PageUtil.getOffset(page, pageSize);
        Map<String,Object> params = new HashMap<>(2);
        params.put("userId",userId);
        params.put("type",type);
        params.put("startNum",startNum);
        params.put("pageSize",pageSize);
        return activityRewardLogDao.getRewardsLog(params);
    }

    /**
     * 查询充值记录
     * @param userId
     * @return
     */
    public List<CoolSummerRechargeAmountDetailVO> getCoolSummerRechargeAmountDetailList(long userId,Integer page,
                                                                                        Integer pageSize) {
        int startNum = PageUtil.getOffset(page, pageSize);
        int endNum = (startNum + pageSize) - 1;
        return coolSummerActivitiesRedisDao.getCoolSummerRechargeAmountDetailVOList(userId,startNum,endNum);
    }

    public CoolSummerRankingResultVO getRankingList(long userId) {
        CoolSummerRankingResultVO coolSummerRankingResultVO = new CoolSummerRankingResultVO();
        CoolSummerDetailVO detailVO = new CoolSummerDetailVO();
        double rechargeAmount=coolSummerActivitiesRedisDao.getUserCountRechargeAmount(userId);
        detailVO.setRechargeAmount(DoubleFormatUtil.doubleFormate(rechargeAmount)+"");
        //奖池
        CoolSummerJackpotVO coolSummerJackpotVO = coolSummerActivitiesRedisDao.getJackpot();
        BigDecimal jackpotDecimal = new BigDecimal(Long.toString(coolSummerJackpotVO.getJackpot()));
        List<CoolSummerRankingList> list = coolSummerRankingListDao.getCoolSummerRankingList();

        BigDecimal sum = new BigDecimal("0.00");
        for(CoolSummerRankingList obj : list){
            sum=sum.add(obj.getRechargeAmount());
        }

        List<CoolSummerRankingListVO> resultList = new ArrayList<>();
        for(int i=0;i<list.size();i++){
            CoolSummerRankingList obj = list.get(i);
            CoolSummerRankingListVO vo = new CoolSummerRankingListVO();
            BigDecimal bigDecimal = obj.getRechargeAmount().multiply(jackpotDecimal).divide(sum,2,
                    RoundingMode.DOWN);
            vo.setEstimatedRewards(bigDecimal.toBigInteger().longValue());
            vo.setRechargeAmount(obj.getRechargeAmount().toString());
            vo.setUserId(obj.getUserId());
            UserCacheVo user = userInfoCache.getUserCacheInfo(vo.getUserId());
            vo.setNickName(user.getNickName());
            resultList.add(vo);

            if(obj.getUserId().longValue() == userId){
                detailVO.setRanking(Integer.toString(i+1));
            }
        }

        if(StringUtils.isBlank(detailVO.getRanking())){
            detailVO.setRanking("未上榜");
        }

        coolSummerRankingResultVO.setUserDetail(detailVO);
        coolSummerRankingResultVO.setList(resultList);

        return coolSummerRankingResultVO;
    }

    @Transactional(rollbackFor = Exception.class)
    public void activityRewards(){
        CoolSummerJackpotVO coolSummerJackpotVO = coolSummerActivitiesRedisDao.getJackpot();
        BigDecimal jackpotDecimal = new BigDecimal(Long.toString(coolSummerJackpotVO.getJackpot()));
        List<CoolSummerRankingList> list = coolSummerRankingListDao.getCoolSummerRankingList();
        BigDecimal sum = new BigDecimal("0.00");
        for(CoolSummerRankingList obj : list){
            sum=sum.add(obj.getRechargeAmount());
        }

        for(CoolSummerRankingList obj : list){
            BigDecimal bigDecimal = obj.getRechargeAmount().multiply(jackpotDecimal).divide(sum,2,
                    RoundingMode.DOWN);
            long userId = obj.getUserId();
            long estimatedRewardsBeans = bigDecimal.toBigInteger().longValue();
            int num = coolSummerRankingListDao.updateCoolSummerRankingIsReceive(userId);
            if(num == 1){
                UserWallet userWallet = new UserWallet();
                userWallet.setBeans(estimatedRewardsBeans);
                userWallet.setUserId(userId);
                int flag = userWalletDao.plusUserWalletBeans(userWallet);
                if(flag>0){
                    BillDetailBeansMqMessageBuilder builder = new BillDetailBeansMqMessageBuilder();
                    BillDetailBeansDTO billDetailBeansDTO = builder.userId(userId).beans(estimatedRewardsBeans)
                            .beansType(BeansType.COOL_SUMMER_RANKING_GIVE_BEANS)
                            .createDate(LocalDate.now(ZoneOffset.of("+8")))
                            .createTime(LocalDateTime.now(ZoneOffset.of("+8"))).build();
                    billDetailBeansMq.getBillDetailBeansMq(billDetailBeansDTO);
                }
            }

        }
    }

}
